﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.SessionState;

namespace Sys.Api
{
    /// <summary>
    /// Api访问类
    /// </summary>
    public static class AccessApi
    {
        /// <summary>
        /// 执行Api请求
        /// </summary>
        /// <param name="context">HttpContext</param>
        /// <returns>结果</returns>
        public static object ProcessRequest(HttpContext context)
        {
            string[] path = context.Request.QueryString["path"].Split('/');

            if (path.Length == 3)
            {
                string space = path[0], name = path[1], method = path[2];

                object classobj = CreateApi(space, name + "Api");

                MethodInfo methodInfo = classobj.GetType().GetMethod(method);

                return methodInfo.Invoke(classobj, GetParameters(context, methodInfo));
            }
            else { return null; }
        }

        /// <summary>
        /// 反射Api
        /// </summary>
        /// <param name="space">名称空间域</param>
        /// <param name="name">类名</param>
        /// <returns>反射Api类</returns>
        public static object CreateApi(string space, string name)
        {
            return Assembly.Load("Sys.Api").CreateInstance("Sys.Api" + "." + space + "." + name);
        }

        /// <summary>
        /// 取得方法参数
        /// </summary>
        /// <param name="context">HttpContext</param>
        /// <param name="methodInfo">方法信息</param>
        /// <returns>参数集合</returns>
        public static object[] GetParameters(HttpContext context, MethodInfo methodInfo)
        {
            ParameterInfo[] plist = methodInfo.GetParameters();

            object[] olist = new object[plist.Length];

            for (int i = 0; i < plist.Length; i++)
            {
                object value = context.Request.Form[plist[i].Name];

                string type = plist[i].ParameterType.FullName;

                if (plist[i].ParameterType == typeof(HttpSessionState))
                {
                    olist[i] = context.Session;
                }
                else if (type.Contains("Sys.Model"))
                {
                    object model = Assembly.Load("Sys.Model").CreateInstance(type);

                    Type t = model.GetType();

                    foreach (var item in t.GetProperties())
                    {
                        object v = context.Request.Form[item.Name];

                        if (v != null)
                        {
                            try
                            {
                                //item.SetValue(model, Convert.ChangeType(v, item.PropertyType), null);

                                //修改成以下这个可解决异常：从System.String到Nullable...System.Boolean 的强制转换无效
                                if (item.PropertyType.IsGenericType)
                                {
                                    //如果不空，则需要赋值
                                    if (!v.Equals(string.Empty))
                                    {
                                        //对于布尔类型需要特殊处理
                                        if (item.PropertyType.GetGenericArguments()[0].Name == "Boolean")
                                        {
                                            if (v.Equals("on"))
                                                v = "True";
                                        }
                                        item.SetValue(model, Convert.ChangeType(v, item.PropertyType.GetGenericArguments()[0]), null);
                                    }
                                }
                                else
                                    item.SetValue(model, Convert.ChangeType(v, item.PropertyType), null);
                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                        }
                    }

                    olist[i] = model;
                }
                else
                {
                    try
                    {
                        olist[i] = Convert.ChangeType(value, plist[i].ParameterType);
                    }
                    catch (Exception ex) { throw ex; }
                }
            }

            return olist;
        }
    }
}
